//== SAGITTARIUS ============================================================================

//== FILEDOC =========================================================================

/** @file lexvec.h
  * @brief Regular vector implementation
  */

//== BEGINNING OF CODE ===============================================================

#ifndef __SAGUTTARUIS__LEXVEC__H_
#define __SAGUTTARUIS__LEXVEC__H_

//== INCLUDES ========================================================================

#include "sagittarius/core/SagittariusCore.h"
#include "sagittarius/lexer/lexcore.h"
#include "sagittarius/lexer/lAST.h"
#include "sagittarius/re/reDC.h"
//#include "sagittarius/lexer/lParser.h"
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief The type of action to take when a pattern is matched
 */
typedef enum {
    /// Do not perform an action when the pattern is matched
    LEX_ACTION_NONE,
    /** @brief Stop the parsing and return the matched pattern
     * @details The parsing can be resumed later.
     */
    LEX_ACTION_STOP,
    /// Reset the parsing state to start if the pattern is matched
    LEX_ACTION_RESET,
    /// Invoke a user-supplied function when a pattern is matched
    LEX_ACTION_USERFUN,
    /// Increment the specified variable when a pattern is matched
    LEX_VAR_INC
} lexvec_action_type;

/**
 * @brief Describes a (semantic) @b action to take when a pattern is matched
 * @details Usually part of a @ref lex_actchain
 */
typedef struct {
    ///The type of action
    lexvec_action_type type;
    /// Variable name, when modifying a var
    LexBuf id;
} lexaction;

/// @brief Destructor for @ref lexaction
void lex_delete_action(lexaction* act);

/**
 * @brief A @b chain of actions to execute when a pattern is matched
 */
typedef struct {
    /// Length of chain
    size_t n;
    /// Actions
    lexaction* a;
} lex_actchain;

/// @brief Constructor
lex_actchain* lex_createActChain();

/// @brief Destructor
void lex_deleteActChain(lex_actchain* c);

/// @brief Add an action
void lex_pushAct(lex_actchain* c, lexaction a);

/// @brief Dump contents (debugging)
void lex_actchain_dump(int fd, lex_actchain* c, int ind_level);

/**
 * @brief Element of lexvec
 * @details Contains the AST for a RE, as well as what
 * to do if the RE is matched.
 */
typedef struct {
    ///@brief Identifier for this exp, if applicable
    LexBuf id;
    int ownid;
    
    ///@brief String representing this exp
    LexBuf exp;
    int ownexp;
    
    ///@brief RE AST node
    lASTNode* r;
    
    ///@brief Name of function to call when matched
    //constLexBuf fun;
    lex_actchain* act;
    int ownact;
    //int ownfun;
    
    
    ///@brief Stop when match is encountered?
    //uint32 stop;
} lexvece;

/** @brief Create an lexvec element
 */
lexvece* create_lexvece();

/** @brief Deep copy a lexvec element
 * @param[in] o Element to copy
 * @returns A deep copy of @a o
 */
lexvece* lexvece_deepCopy(lexvece* o);

/** @brief lexvece destructor
 */
void destroy_lexvece(lexvece*);

/** @brief Computes the DC of the element
 */
void lexvec_computeDCe(lexvece* e);

/** @brief Dumps the contents of the element
 */
void lexvec_dumpElt(int fd, lexvece* e, int ind_level);

/**
 * @brief A vector of REs in parallel
 * @details Computes the DC (@ref reDC.h) of each
 */
typedef struct {
    /// @brief Length of the vector
    size_t n;
    
    /// @brief Heap array of REs
    lexvece** e;
    
    /// @brief The derivative classes of the vector - used in DFA construction
    RE_DerivClass* d;
} lexvec;

/** @brief Initialize a lexvec
 */
void init_lexvec(lexvec* v);

/** @brief Create a lexvec
 * @details Unlike @ref init_lexvec, this allocates memory.
 * It also initializes the fields of the created lexvec.
 * @returns A new lexvec
 */
lexvec* create_lexvec();

/** @brief lexvec destructor
 */
void destroy_lexvec(lexvec* v);

/** @brief Push an elt onto a lexvevc
 */
void lexvec_push(lexvec* v, lexvece* e);

/** @brief Computes the DC for the entire vector
 * @details The DC for @a v is simply the mesh of the DCs of the
 * elements of @a v. Explained in @ref OwensPaper "Owens et al."
 */
void lexvec_computeDC(lexvec* v);

/** @brief Test two @a lexvecs for equality
 * @returns 1 if @a u == @a v, 0 otherwise
 */
int lexvec_compEq(lexvec* u, lexvec* v);

int lexvec_isNull(lexvec* v);

/** @brief Remove action-less items
 * @details Builds a new vector containing only items that have associated actions
 */
lexvec* lexvec_elidePassive(lexvec* v);

/** @brief Dumps the contents of the vector
 */
void lexvec_dump(int fd, lexvec* v, int ind_level);

#ifdef __cplusplus
}//extern "C"
#endif

#endif
